package com.mcp.converter.domain.converter.impl;

import com.mcp.converter.domain.checker.CompatibilityResult;
import com.mcp.converter.domain.checker.IncompatiblePoint;
import com.mcp.converter.domain.converter.ConversionDetail;
import com.mcp.converter.domain.converter.ConversionResult;
import com.mcp.converter.domain.converter.ConversionSuggestion;
import com.mcp.converter.domain.converter.SQLConverter;
import com.mcp.converter.shared.response.sql.SQLParseResult;
import com.mcp.converter.shared.response.sql.SQLElement;
import com.mcp.converter.domain.rule.conversion.ConversionRule;
import com.mcp.converter.domain.rule.manager.RuleManager;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * SQL转换引擎实现类
 * 负责将不兼容的Oracle SQL语句转换为OceanBase兼容的SQL语句
 */
@Service
public class SQLConverterImpl implements SQLConverter {
    
    @Resource
    private RuleManager ruleManager;
    
    @Override
    public ConversionResult convert(SQLParseResult parseResult, CompatibilityResult compatibilityResult) {
        if (parseResult == null) {
            throw new IllegalArgumentException("SQL解析结果不能为空");
        }
        
        if (compatibilityResult == null) {
            throw new IllegalArgumentException("兼容性检测结果不能为空");
        }
        
        // 如果完全兼容，直接返回原始SQL
        if (compatibilityResult.isCompatible()) {
            return new ConversionResult(parseResult.getOriginalSQL(), parseResult.getOriginalSQL(), true);
        }
        
        // 加载转换规则
        RuleManager.LoadResult loadResult = ruleManager.loadRules(RuleManager.RuleType.CONVERSION);
        if (!loadResult.isSuccess()) {
            throw new RuntimeException("加载转换规则失败: " + loadResult.getMessage());
        }
        
        // 创建转换结果
        ConversionResult result = new ConversionResult();
        result.setOriginalSQL(parseResult.getOriginalSQL());
        
        // 创建转换上下文
        ConversionContextImpl context = new ConversionContextImpl(parseResult.getOriginalSQL());
        
        // 获取不兼容点列表并进行转换
        List<IncompatiblePoint> incompatiblePoints = compatibilityResult.getIncompatiblePoints();
        for (IncompatiblePoint incompatiblePoint : incompatiblePoints) {
            applyConversionRule(incompatiblePoint, context, result);
        }
        
        // 设置转换后的SQL
        String convertedSQL = context.getCurrentSQL();
        result.setConvertedSQL(convertedSQL);
        
        // 设置转换详情
        result.setConversionDetails(context.getConversionDetails());
        
        // 设置转换是否成功
        result.setSuccessful(true);
        
        return result;
    }
    
    @Override
    public ConversionSuggestion getSuggestion(IncompatiblePoint incompatiblePoint) {
        if (incompatiblePoint == null) {
            throw new IllegalArgumentException("不兼容点不能为空");
        }
        
        // 根据不兼容点查找对应的转换规则
        RuleManager.RuleQueryCondition condition = new RuleManager.RuleQueryCondition();
        condition.setType(incompatiblePoint.getType().name());
        condition.setName(incompatiblePoint.getName());
        
        List<ConversionRule> rules = ruleManager.queryRules(
            RuleManager.RuleType.CONVERSION, 
            condition
        );
        
        if (rules.isEmpty()) {
            // 如果找不到对应的规则，返回一个默认的建议
            ConversionSuggestion suggestion = new ConversionSuggestion(incompatiblePoint);
            suggestion.setSuggestion("无法自动转换，请参考OceanBase官方文档手动修改");
            suggestion.setAutoConvertible(false);
            suggestion.setComplexity(ConversionSuggestion.Complexity.NOT_CONVERTIBLE);
            return suggestion;
        } else {
            // 返回找到的第一个规则的建议
            return rules.get(0).getConversionSuggestion();
        }
    }
    
    /**
     * 应用转换规则
     * @param incompatiblePoint 不兼容点
     * @param context 转换上下文
     * @param result 转换结果
     */
    private void applyConversionRule(IncompatiblePoint incompatiblePoint, ConversionContextImpl context, ConversionResult result) {
        // 查找匹配的转换规则
        RuleManager.RuleQueryCondition condition = new RuleManager.RuleQueryCondition();
        condition.setType(incompatiblePoint.getType().name());
        condition.setName(incompatiblePoint.getName());
        
        List<ConversionRule> rules = ruleManager.queryRules(
            RuleManager.RuleType.CONVERSION,
            condition
        );
        
        if (!rules.isEmpty()) {
            // 找到匹配的规则，应用转换
            ConversionRule rule = rules.get(0);
            SQLElement element = incompatiblePoint.getElement();
            if (element != null && rule.matches(element)) {
                String converted = rule.convert(element, context);
                // 更新上下文中的SQL
                context.updateSQL(element, converted);
            }
        }
    }
    
    /**
     * 转换上下文实现类
     */
    private static class ConversionContextImpl implements ConversionRule.ConversionContext {
        private String originalSQL;
        private String currentSQL;
        private List<ConversionDetail> conversionDetails;
        
        public ConversionContextImpl(String originalSQL) {
            this.originalSQL = originalSQL;
            this.currentSQL = originalSQL;
            this.conversionDetails = new ArrayList<>();
        }
        
        @Override
        public String getOriginalSQL() {
            return originalSQL;
        }
        
        @Override
        public String getCurrentSQL() {
            return currentSQL;
        }
        
        @Override
        public void addConversionDetail(String original, String converted, String reason) {
            ConversionDetail detail = new ConversionDetail();
            detail.setOriginal(original);
            detail.setConverted(converted);
            detail.setReason(reason);
            conversionDetails.add(detail);
        }
        
        /**
         * 更新SQL
         * @param element 被转换的元素
         * @param converted 转换后的内容
         */
        public void updateSQL(SQLElement element, String converted) {
            if (element != null && element.getPosition() != null) {
                int startIndex = element.getPosition().getStartIndex();
                int endIndex = element.getPosition().getEndIndex();
                if (startIndex >= 0 && endIndex > startIndex && endIndex <= currentSQL.length()) {
                    currentSQL = currentSQL.substring(0, startIndex) + converted + currentSQL.substring(endIndex);
                }
            }
        }
        
        /**
         * 获取转换详情列表
         * @return 转换详情列表
         */
        public List<ConversionDetail> getConversionDetails() {
            return conversionDetails;
        }
    }
}
